
	//global variables
	//Service (IP+PORT)IP+ID-- > Map Of 
	//IP -- > Map of Services  -- > One App per service -- > Remote serices per application 
    var serverIpsDataContainer={};

	//global helper fuctions
	Array.prototype.contains = function(k) {
	        for(var p in this)
	            if(this[p] == k)
	                return true;
	        return false;
	    }
	    
    	function inserToSet(mySet,key){
		if (mySet.indexOf(key)<0){
        		mySet.push(key);
        		return true;
        	}
        	return false;
    	}

    	function isInSet(mySet,key){
		if (mySet.indexOf(key)>=0){
        		return true;
        	}
        	return false;
    	}

    	function findInSet(mySet,key){
    		if (mySet.indexOf(key)>=0){
            		return mySet[mySet.indexOf(key)];
            	}
            	return null;
        }


	//netstat lines processing 
    	function findProcessName(lines,nextline,stopRegexPattern ){
			var search=true;
	        var processNamePattern=new RegExp(".*\\[");
			var processName;	
			while (search && (nextline <= numberOfLines) ){
				if (stopRegexPattern.test(lines[nextline])){
					search=false;
				}else if (processNamePattern.test(lines[nextline])){
					search=false;
					processName=lines[nextline];
				}
				nextline=nextline+1;				
			}
			return processName;
    	}
    	
    	
    	function getRemoteServerIpv4(line){
    		var ServerIp;
			var tokens = (line.split(/\s+/));
		
			if (tokens[3].split(':').length >0)
	    			ServerIp = (tokens[3].split(':'))[0];
	    	return ServerIp;
    	}

    	function getLocaleServerIpv4(line){
    		var ServerIp;
			var tokens = (line.split(/\s+/));
		
			if (tokens[2].split(':').length >0)
	    			ServerIp = (tokens[2].split(':'))[0];
	    	return ServerIp;
    	}

    	
    	function getLocalServerPort(line){
    		var currentPort;
			var tokens = (line.split(/\s+/));
		
			if (tokens[2].split(':').length >0)
				currentPort = (tokens[2].split(':'))[1];
	    	return currentPort;
    	}

    	function getRemoteServerPort(line){
    		var currentPort;
			var tokens = (line.split(/\s+/));
		
			if (tokens[3].split(':').length >0)
				currentPort = (tokens[3].split(':'))[1];
	    	return currentPort;
    	}
    	
    
    	
    	function isConnectionToCurrentService(ports,pid,port){
//    		console.log("pidPort:"+ports[port]+ " port:"+port +" pid:"+pid)
    		return ports[port]==pid;
    	}
    	    	
    	
    	function addNewRelatedPIDs(pid1,pid2,processesToApplications,detectedAppNum){
		//several optional cases 
		//1. two PID's exist on same application -do nothing
		//2. one PID exist - put the second pid on same application
		//3. two PID's missing - insert them both on new application 
		//4. two PID's exist on different applications - need to unify applications
		
		//validate input
		if (typeof (pid1) =='undefined' || typeof (pid2) =='undefined')
			return detectedAppNum;
		
		var app1=processesToApplications[pid1];
		var app2=processesToApplications[pid2];
		
		if ( (typeof app1 != 'undefined' ) && (typeof app2 != 'undefined')){
			//case 1 do nothing
			if (app1!=app2){
				//case 4 the processes already mapped to two differnt applications
				//this one is complicated 
				//need to union applications of pid1 and pid2
				//alert ("union" +pid1 +" "+pid2);
				for (pid in processesToApplications){
					if (processesToApplications[pid] == app2){
						processesToApplications[pid]=app1;
					}
				}
			}
		}else if(app1 ==undefined && app2 !=undefined){
			//case 2 insert pid1 to application of pid2
			processesToApplications[pid1]=app2;
		}else if(app2 ==undefined && app1 !=undefined){
			//case 2 insert pid2 to application of pid1
			processesToApplications[pid2]=app1;
		}else if((app2 ==undefined && app1 ==undefined ) ||(processesToApplications.length==0) ){
			//case 3 two PIDs missing or empty map
			detectedAppNum++;
			processesToApplications[pid2]=detectedAppNum;
			processesToApplications[pid1]=detectedAppNum;
		}
    		
    		
    		return detectedAppNum;
    		
    	}
    	

    	//integration with UI
        
        
        function getAppType(port){
        	return (port==1433)?'DB':'server';
        }
        
        function getListOfApplicationPids(ip,appId){
        	var ptA=serverIpsDataContainer[ip]['processesToApplications'];
        	var listOfPids= new Array();
        	for (var key in ptA){
        		if (ptA[key]==appId) {
        			listOfPids.push(key);
        		  }
        	}
        	return listOfPids;
        }
        
        
        function addRemoteSericesAsChilds(ip,appID,arrayOfPids){
        	var childs=new Array(); 
        	var ptS= serverIpsDataContainer[ip]['pidsToRemoteServices'];
        	for (var i=0 ;i<arrayOfPids.length;i++){
        		pid=arrayOfPids[i];
        		if (ptS[pid]) {
        			for (var j=0;j<ptS[pid].length;j++)
        				inserToSet(childs, ptS[pid][j]);
        		  }
        	}
        	return childs;
        }
        
        function createLeaf(ip,port,isHead,appType){
        	var obj = {
        			id:ip+":"+port,
        			name:ip+":"+port,
        	        data:{
        	              name:'Leaf',
        	              head:isHead,
        	              port:port,
        	              processCount:0,
        	              mytype:appType
        	          },
        	          children:[]
        		};
        	return obj;
        }

    	
    	function createStructure(ip,port,pidName,processNum,isHead,appType){
        	var obj = {
        			id:ip+":"+port,
        			name:pidName,
        	        data:{
        	              name:pidName,
        	              head:isHead,
        	              port:port,
        	              processCount:processNum,
        	              mytype:appType
        	          },
        	          children:[]
        		};
        	return obj;
        }
        
        //node service ID is in format "ip:port" the output is object created by createStructure
        function getNodeDeails(nodeServiceID,head){
        	var ip=nodeServiceID.split(":")[0];
        	var port=nodeServiceID.split(":")[1];
        	
        	
        	var pidNum=serverIpsDataContainer[ip]['listenPortsToPids'][port];
        	var pidName=serverIpsDataContainer[ip]['pidsToProcessName'][pidNum];
        	var appId=serverIpsDataContainer[ip]["processesToApplications"][pidNum];
        	
        	var processNum=0;
        	//count processes which belong to same application
        	var arrayOfPids=getListOfApplicationPids(ip,appId);
        	if (arrayOfPids.length>0){
        		processNum=arrayOfPids.length;
        	} else{
        		console.log ('No Pid found');
        	}	

        	var isHead=false;
        	var appType=getAppType(port);
        	var obj= createStructure(ip,port,pidName,processNum,isHead,appType);
        	var cArray=addRemoteSericesAsChilds(ip,appId,arrayOfPids);
        	obj.children=cArray;
        	return obj;
        }



	//return HTML display format and fill the global object (serverIpsDataContainer) with data
        function parseTextFile(textFile){
        	numberOfLines= textFile.split('\n').length;
        	var lines=textFile.split('\n');
        	       	
        	
        	//in the file there are 2 types of TCP connections 
        	//TCP connections for processes in this machine ,and TCP connections from the machine to other process
        	//pattren for listen process on this machine

        	var listenPattern=new RegExp(".*TCP.*LISTENING.*");
        	
        	//pattren of all TCP  connections
        	var tcpPattern=new RegExp(".*TCP.*");
        	var processes=new Array();
        	var pids = new Array();
        	//var listenPortsToPids= new Object();
        	
        	//var processesToApplications= new Object();
        	//var pidsToProcessName= new Array();
        	var applicationsToRemoteServers= new Array();
        	
        	var currentServerIps = new Array(); 
        	var remoteServersConnected= new Array();
        	var remoteServersIpsAndPorts= new Array();
        	//this is map of Set of remote services
        	//var pidsToRemoteServices =new Object();
        	//each Pid is mapped to array of remoteServicesPerPid
        	var listenPortsToPids = {};
        	var processesToApplications= {};
        	var pidsToRemoteServices= {};
        	var pidsToProcessName= {};
        	//map  of pid to string which lists open ports
        	var pidsToPorts={};

        	var count=0;
			var detectedAppNum=0;
		
			//loop all the lines
			//collect the following data
			//1. Map of all PID and listen port (find the services run on the machine)
			//
          	
			for (var i=0;i<numberOfLines;i++){
          		var tokens = (lines[i].split(/\s+/));
        		if (listenPattern.test(lines[i])){
        			var nextline=i+1;
               		//extract the port 
               		var port = (tokens[2].split(':'))[(tokens[2].split(':').length)-1];
					//extract PID
					var pid = tokens[5];
					//console.log(pid);
					if (pid != 0){
						inserToSet(pids,pid);
						listenPortsToPids[port]=pid;
						if (pidsToPorts.hasOwnProperty(pid)){
							var array=(pidsToPorts[pid].split(','));
							inserToSet(array, port);
							pidsToPorts[pid]=array.toString();
							//console.log("arrayLen:"+array.length);
							//console.log(pidsToPorts[pid]);
						}else{
							pidsToPorts[pid]=port;
							
						}

						if (typeof (processesToApplications[pid])== 'undefined'){
							detectedAppNum++;
							processesToApplications[pid]=detectedAppNum;
						}
						count++;
					}
					
					//extract Process Name
					var processName=findProcessName(lines,nextline,tcpPattern);
					if (typeof processName != 'undefined'){
	        				pidsToProcessName[pid]=processName;
	        				inserToSet(processes,processName);
	        				
	        			}
	        		}	
        	}
        	
       		currentServerIps.push("127.0.0.1");
        	//do 2 things
        	//1. group all services in the machine to application (find related process IDs)
        	//2. Map application to remote machines
        	//console.log("listenPortsToPids:");
        	//console.log(listenPortsToPids);
        	for (var i=0;i<numberOfLines;i++){
          		var tokens = (lines[i].split(/\s+/));
        		if (listenPattern.test(lines[i])){
				//first loop done akk the stuff here	
        		}else if (tcpPattern.test(lines[i])){
        		
					//extract PID
					var pid = tokens[5];
					//extract remote Server IPv4				
	        		var remoteServerIp=getRemoteServerIpv4(lines[i]);
					var localServerIp=getLocaleServerIpv4(lines[i]);
	        		var localPort =getLocalServerPort(lines[i]);
	        		//var remotePort=getRemoteServerPort(lines[i]);
	        		
	        		inserToSet(currentServerIps,localServerIp);
					if (typeof remoteServerIp != 'undefined' && typeof localPort != 'undefined'){
						if(!isInSet(currentServerIps,remoteServerIp)){
							//This is extranal connection from our machine to remote
							//check if the our process initiate the connection
							
							//inserToSet(remoteServersConnected,remoteServerIp);
							if (pid != 0 && !isConnectionToCurrentService(listenPortsToPids,pid,localPort)){
								//we want to insert only connection from our service outside
								//console.log("Local port is "+localPort);
								var remoteServicesSet;
								if (pidsToRemoteServices.hasOwnProperty(pid)){
									remoteServicesSet = pidsToRemoteServices[pid];
									inserToSet(remoteServicesSet,tokens[3]);
									//console.log("pid:"+pid+" service"+tokens[3]+" size is:"+remoteServicesSet.length);
								}else{//there is no an array, need to initiate
									var remoteServicesSet =new Array();
									inserToSet(remoteServicesSet,tokens[3]);
									pidsToRemoteServices[pid]=remoteServicesSet;
									//console.log("new pid:"+pid+" service"+tokens[3]+" size is:"+remoteServicesSet.length+" pidsToRemoteServices length:"+pidsToRemoteServices.length);
								}	
						
							}//else do nothing (we don't have pid)
						}else{
							//This is internal connection 
							if ( pid!=0 ){
								var secondPort = (tokens[3].split(':'))[1];
								var secondPid=	listenPortsToPids[secondPort];
								if (typeof (secondPid)!='undefined'){
									detectedAppNum= addNewRelatedPIDs(pid,secondPid,processesToApplications,detectedAppNum);
								}
							}
						}
					}
        		}
        	}
        	
        	
        	//console.log ('processesToApplications');
        	//console.log(processesToApplications);
        	//console.log ("listenPortsToPids");
        	//console.log(serverIpsDataContainer[fname]['listenPortsToPids']);
        	//console.log("pidsToRemoteServices");
        	console.log(listenPortsToPids);
        	var FileHtmlDisplay="<br>";
        	FileHtmlDisplay=FileHtmlDisplay+"<table border=\"1\">" + "<th>application Id</th>"+ "<th>Process Name</th>" +"<th>Remote Service</th>"+"<th>Open Ports</th>";
        	for (x in processesToApplications){
        		
        		function sortNumber(a,b) {
        		    return a - b;
        		}

        		//sort the port numbers
        		var pTP='undefined';
        		if (typeof (pidsToPorts[x])!='undefined'){
        			pTP=(pidsToPorts[x].split('+')).sort(sortNumber).toString();
        		}
        		FileHtmlDisplay =FileHtmlDisplay +"<tr>" +"<td> "+processesToApplications[x] +"</td><td> "+ pidsToProcessName [x]+ "</td><td> "+pidsToRemoteServices[x] +"</td><td> "+ pTP+ "</td> </tr>" ;
        	}
        	FileHtmlDisplay=FileHtmlDisplay+"</table>";
        	return FileHtmlDisplay;
        }
